local oo = require("SharedLibs.BaseLib")
local co = require("SharedLibs.CoroLib")

Debugger = require("SharedLibs.Debugger")

IReadOnlyProperty = require("SharedLibs.Signal.IReadOnlyProperty");
ISignal = require("SharedLibs.Signal.ISignal");
Signal = require("SharedLibs.Signal.Signal");

--[[
	把两个属性组合成一个二元组属性。二元组属性的值是 二元组
	当任意一个子属性变化时，二元组属性都会变化（会触发事件）。
]] 
local TupleProperty = oo.class("TupleProperty");
TupleProperty:implements(IReadOnlyProperty);

function TupleProperty:constructor(p1, p2, name)
	assert(p1 and p2);
	self._changed = Signal.new("PropertyChanged");	

	self._p1 = p1;
	self._p2 = p2;

	self.name = name or "TupleProperty";
	self.isTuple = true;

	self._listenerCount = 0;
end

function TupleProperty:GetValue()
	local p1 = self._p1;
	local p2 = self._p2;
	if not p1.isTuple and not p2.isTuple then
		return p1:GetValue(), p2:GetValue();
	else
		local t1 = {p1:GetValue()};
		local t2 = {p2:GetValue()};
		local n1 = #t1;
		for i=1,#t2 do
			t1[n1+1] = t2[i];
		end
		return table.unpack(t1);
	end	
end

function TupleProperty:On(listener)	
	self._listenerCount = self._listenerCount + 1; 
	self._changed:On(listener);

	if self._listenerCount == 1 then
		self._onChildChanged = function(value)
			self._changed:Emit(self:GetValue());
		end;
		self._p1:On(self._onChildChanged);
		self._p2:On(self._onChildChanged);
	end
end

function TupleProperty:Off(listener)
	self._listenerCount = self._listenerCount - 1; 
	assert(self._listenerCount >= 0);
	self._changed:Off(listener);

	if self._listenerCount == 0 then
		self._p1:Off(self._onChildChanged);
		self._p2:Off(self._onChildChanged);
		self._onChildChanged = nil;
	end
end

return TupleProperty;
